package val.to;

import java.lang.ref.SoftReference;
import java.util.LinkedHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import val.to.config.Constants;
import android.graphics.Bitmap;
import android.util.Log;

//Currently, The thread safety is very naive: single writer/reader.
public class ImageCache {
	
	public class LRUCache<K,V> extends LinkedHashMap<K,V> {
		private static final long serialVersionUID = 1L;
		private int capacity; // Maximum number of items in the cache.
	
	    public LRUCache(int capacity) { 
	        super(capacity + 1, 1.0f, true); // Pass 'true' for accessOrder.
	        this.capacity = capacity;
	    }
	     
	    protected boolean removeEldestEntry(Entry<K,V> entry) {
	        return (size() > this.capacity);
	    } 
	}
	
	private static ImageCache instanceLargePhotos;
	private static ImageCache instanceSmallPhotos;
	private static ImageCache instanceThumbnailsPhotos;
	private static ImageCache instanceUserPictures;
	
	private LRUCache<String, SoftReference<Bitmap>> mCache;
	
    private ImageCache(int maxItems) {
    	mCache = new LRUCache<String, SoftReference<Bitmap>>(maxItems);
    }

    public static synchronized ImageCache getInstanceLarge() {
        if (instanceLargePhotos == null) {
        	instanceLargePhotos = new ImageCache(Constants.LARGE_IMAGE_CACHE_SIZE);
        }
        
        return instanceLargePhotos;
    }
    
    public static synchronized ImageCache getInstanceSmallPhotos() {
        if (instanceSmallPhotos == null) {
        	instanceSmallPhotos = new ImageCache(Constants.SMALL_IMAGE_CACHE_SIZE);
        }
        
        return instanceSmallPhotos;
    }
    
    public static synchronized ImageCache getInstanceThumbnailsPhotos() {
        if (instanceThumbnailsPhotos == null) {
        	instanceThumbnailsPhotos = new ImageCache(Constants.THUMBNAIL_IMAGE_CACHE_SIZE);
        }
        
        return instanceThumbnailsPhotos;
    }
    
    public static synchronized ImageCache getInstanceUserPictures() {
        if (instanceUserPictures == null) {
        	instanceUserPictures = new ImageCache(Constants.USER_PICTURES_CACHE_SIZE);
        }
        
        return instanceUserPictures;
    }
    
    public Bitmap tryGetBitmap(String path){
    	
    	SoftReference<Bitmap> wr;
    	synchronized (mCache) {
        	wr = mCache.get(path);			
		}
    	
    	if (wr != null){
    		if (wr.get() == null){
    			Log.w(Constants.TAG, "Soft refed bitmap was collected.");
    			synchronized (mCache) {
        			mCache.remove(path);	
				}
    			return null;
    		}
    		
    		return wr.get();
    	}
    	
        return null;
    }
    
    public void encache(String path, Bitmap bmp){
    	SoftReference<Bitmap> sr = new SoftReference<Bitmap>(bmp);
    	synchronized (mCache) {
        	mCache.put(path, sr);	
		}
    }
    
    public void clear(){
    	synchronized (mCache) {
        	mCache.clear();	
		}
    } 
}
